package com.zy.nettypoject.netty.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Iterator;

@Slf4j
public class ServerSelector {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel sc = ServerSocketChannel.open();
        sc.configureBlocking(false);
        sc.bind(new InetSocketAddress(8099));
        //注册
        sc.register(selector, SelectionKey.OP_ACCEPT);//注册集合
        while (true){
            //等待客户端链接事件发生
            selector.select();
            //只会添加新的事件，不会主动删除
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                log.info("当前处理的事件：{}",key);
                if (key.isAcceptable()){
                    //接收到了读取
                    ServerSocketChannel channel = (ServerSocketChannel)key.channel();
                    SocketChannel accept = channel.accept();
                    accept.configureBlocking(false);
                    accept.register(selector, SelectionKey.OP_READ);//事件监听集合
                    log.info("处理通道：{}",channel);
//                    key.cancel();
                }else if (key.isReadable()){
                    try {
                        ByteBuffer allocate = ByteBuffer.allocate(16);
                        SocketChannel channel = (SocketChannel)key.channel();
                        int read = channel.read(allocate);
                        if (read == -1){
                            //客户端正常结束
                            key.cancel();
                        }else {
                            allocate.flip();
                            log.info("接收到客户端的值：{}", Charset.defaultCharset().decode(allocate));
                        }
                    }catch (Exception e){
                        log.info("客户端挂了");
                        key.cancel();//客户端挂了会返回个read，执行结束也会返回个read
                        e.printStackTrace();
                    }
                }else if (key.isConnectable()){
                    SelectableChannel channel = key.channel();
                    log.info("客户端链接：{}",channel);
                }
                //处理事件后移除当前事件
                iterator.remove();
            }
        }
    }




}
